<template>
  <div class="app">
    <div class="takeView">
      <canvas ref="takeView"></canvas>
    </div>
    <div class="box" ref="box">
      <img
        class="plane"
        ref="plane"
        id="plane"
        src="@/assets/images/plane.png"
      />
      <template v-if="zidanArr.length > 0">
        <span
          class="zidan"
          ref="zidan"
          v-for="(item, index) in zidanArr"
          :key="index"
          :style="{ left: `${item.x}px`, top: `${item.y}px` }"
        ></span>
      </template>
      <template v-if="dijiArr.length > 0">
        <img
          class="diji"
          v-for="(item, index) in dijiArr"
          :key="'diji_' + index"
          src="@/assets/images/hostile.png"
          :style="{ left: `${item.x}px`, top: `${item.y}px` }"
        />
      </template>
      <template v-if="explosions.length > 0">
        <img
          class="explosion"
          v-for="(explosion, index) in explosions"
          :key="'explosion_' + index"
          src="@/assets/images/blast.gif"
          :style="{ left: `${explosion.x}px`, top: `${explosion.y}px` }"
        />
      </template>
      <template v-if="heartsions.length > 0">
        <img
          class="explosion"
          v-for="(hearts, index) in heartsions"
          :key="'hearts' + index"
          src="@/assets/images/heartOut.gif"
          :style="{ left: `${hearts.x}px`, top: `${hearts.y}px` }"
        />
      </template>
      <template v-if="awardArr.length > 0">
        <img
          class="award"
          v-for="(item, index) in awardArr"
          :key="'award_' + index"
          src="@/assets/images/heart.gif"
          :style="{ left: `${item.x}px`, top: `${item.y}px` }"
        />
      </template>
    </div>
    <div class="model">
      <div class="model-item model-left">
        <moldVue
          :directionX="modelParmas.directionX"
          :directionY="modelParmas.directionY"
        />
        <pushVue :yaoganX="modelParmas.yaoganX" />
      </div>
      <div class="model-item model-right">
        <pedalVue :pedalX="modelParmas.pedalX" />
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import moldVue from "@/components/modelComponents/moldVue/mold.vue";
import pedalVue from "@/components/modelComponents/pedal/pedal.vue";
import pushVue from "@/components/modelComponents/push/push.vue";
import pubsub from "pubsub-js";
export default {
  components: {
    moldVue,
    pedalVue,
    pushVue,
  },
  data() {
    return {
      boxWidth: 1000,
      boxHeight: 800,
      plane: null, //飞机元素
      zidanArr: [], //子弹数组
      dijiArr: [], //敌机数组
      explosions: [], //爆炸特效数组
      heartsions: [], //心跳特效数组
      awardArr: [], // 添加奖励数组
      jishiqi: null, //定时器
      dijiJishi: null, //敌机定时器
      zidanadd: null, //子弹生成计时器
      dijiadd: null, // 敌机生成计时器
      awardAdd: null, // 添加奖励生成计时器
      planeSocer: {
        score: 0, //爱心奖励分数
        hearts: 0, //爱心生成数
        crash: 0, //碰撞飞机数
        strike: 0, //打击飞机数
        enemys: 0, //敌机生成数
      },
      destoryFun: "", // 销毁对象
      //游戏控制器控制飞机
      situationIndex: -1,
      speedIndex: -1,
      balanceIndex: -1,
      requestAnimationFrameId: null,
      requestAnimationSpeedFrameId: null,
      requestAnimationBalanceFrameId: null,
      gamepads: [],
      gameContiner: null,
      isFiring: false,
      startTime: null,
    };
  },
  computed: {
    ...mapGetters(["rockerSpeed", "difficulty", "modelParmas", "getWebSocket"]),
  },
  beforeDestroy() {
    pubsub.unsubscribe(this.destoryFun);
  },
  methods: {
    destroy() {
      console.log("游戏二移除监听");
      this.closeTime();
      this.stopSituationBalanceGamepad();
      this.stopSituationGamepad();
      this.stopSpeedGamepad();
      window.removeEventListener("gamepadconnected", this.gamepadConnected);
      window.removeEventListener(
        "gamepaddisconnected",
        this.gamepadDisconnected
      );
    },
    //获取dom的x和y坐标
    getDomXY() {
      let bulletWidth = 30;
      let x = this.plane.offsetLeft - bulletWidth / 2;
      let y = this.plane.offsetTop - 3;
      let zidanobj = { x, y };
      this.zidanArr.push(zidanobj);
    },
    //碰撞检测
    timsetIntval() {
      this.jishiqi = setInterval(() => {
        if (this.zidanArr.length > 0) {
          this.zidanArr.forEach((item, index) => {
            if (item.y < 5) {
              this.zidanArr.splice(index, 1);
            } else {
              item.y = item.y - 45;
            }
          });
        }
      }, 20);
    },
    //子弹添加
    zidanBtnadd() {
      this.zidanadd = setInterval(() => {
        this.getDomXY();
      }, 500);
    },
    //敌机添加
    dijiAdd() {
      // console.log(this.difficulty * 6, (8 / this.difficulty) * 600);
      this.dijiadd = setInterval(() => {
        if (this.dijiArr.length > this.difficulty * 6) {
          return;
        }
        let y = 0;
        let x = Math.random() * (this.boxWidth - 120);
        let dijiObj = { x, y };
        this.dijiArr.push(dijiObj);
        this.planeSocer.enemys++;
      }, (4 / this.difficulty) * 600);
    },
    //碰撞消除
    dijixing() {
      this.dijiJishi = setInterval(() => {
        this.dijiArr.forEach((item, index) => {
          if (item.y > this.boxHeight - 50) {
            this.dijiArr.splice(index, 1);
          } else {
            item.y = item.y + 5;
          }
        });
      }, 20);
    },
    //爱心奖励添加方法
    awardAddFun() {
      this.awardAdd = setInterval(() => {
        if (this.awardArr.length == this.difficulty * 3) {
          return;
        }
        let y = 0; // 固定 y 值为 0
        let x =
          Math.random() < 0.1
            ? -Math.random() * 100
            : Math.random() * (this.boxWidth - 50); // 在 x 轴上生成随机位置
        let awardObj = { x, y, xSpeed: 5, ySpeed: 2, collisionCount: 0 };
        this.awardArr.push(awardObj);
        this.planeSocer.hearts++;
        // console.log(this.awardArr.length > this.difficulty * 3);
      }, (12 / this.difficulty) * 1000);
    },
    //更新统计表
    updataPlayScoer() {
      this.$store.commit("updatePlanSocerKey", this.planeSocer);
      let score = {
        time: new Date().getTime(),
        code: "planeGameData",
        gameScore: this.planeSocer,
      };
      this.getWebSocket.send(JSON.stringify(score));
    },
    // 爱心奖励移动
    awardMove() {
      setInterval(() => {
        this.awardArr.forEach((item, index) => {
          item.x += item.xSpeed;
          item.y += item.ySpeed;
          if (item.x + 50 > this.boxWidth) {
            item.xSpeed = -5;
          }
          if (item.x < 0) {
            item.xSpeed = 5;
          }
          if (item.y > this.boxHeight) {
            this.awardArr.splice(index, 1);
          }
        });
      }, 20);
    },
    //获取dom高度
    getDomHeight() {
      this.boxHeight = this.$refs.box.offsetHeight;
      this.boxWidth = this.$refs.box.offsetWidth;
    },
    //绘制总览圆点
    drawPlane(x, y, color) {
      this.takeViewCtx.beginPath();
      this.takeViewCtx.arc(x / 10, y / 10, 4, 0, 2 * Math.PI);
      this.takeViewCtx.fillStyle = color;
      this.takeViewCtx.fill();
    },
    //绘制总览奖励圆点
    drawAward(x, y, color) {
      this.takeViewCtx.beginPath();
      this.takeViewCtx.arc(x / 10, y / 10, 3, 0, 2 * Math.PI);
      this.takeViewCtx.fillStyle = color;
      this.takeViewCtx.fill();
    },
    //清除所有定时器
    closeTime() {
      clearInterval(this.jishiqi);
      clearInterval(this.dijiJishi);
      clearInterval(this.zidanadd);
      clearInterval(this.dijiadd);
      clearInterval(this.awardAdd); // 清除奖励生成计时器
      clearInterval(this.startTime);
    },
    //初始化总览canvas
    initCanvas() {
      // 初始化 Canvas
      this.takeView = this.$refs.takeView;
      this.takeViewCtx = this.takeView.getContext("2d");
      this.takeViewCtx.fillRect(
        0,
        0,
        this.takeView.width,
        this.takeView.height
      );
    },
    //初始化飞机
    initPlan() {
      this.plane = document.getElementById("plane");
      const planeOffset = {
        planeOffsetX: this.plane.style.left,
        planeOffsetY: this.plane.style.top,
      };
      this.$store.commit("updateFlyDataKey", planeOffset);
      this.gameContiner = this.$parent.$el;
      console.log("初始化飞机");
      window.addEventListener("gamepadconnected", this.gamepadConnected);
      window.addEventListener("gamepaddisconnected", this.gamepadDisconnected);
    },
    //游戏开始
    actionGame() {
      this.timsetIntval();
      this.dijiAdd();
      this.dijixing();
      this.awardAddFun();
      this.awardMove();
      this.startTime = setInterval(() => {
        this.updataPlayScoer();
      }, 56);
    },
    //输出所有设备
    gamepadConnected(e) {
      this.gamepads.push(e.gamepad);
      this.updateControllerInfo();
      console.log("输出所有设备", this.gamepads);
    },
    gamepadDisconnected(e) {
      console.log("Gamepad disconnected from index " + e.gamepad.index);
      var index = this.gamepads.indexOf(e.gamepad);
      if (index !== -1) {
        this.gamepads.splice(index, 1);
        this.updateControllerInfo();
      }
    },
    updateControllerInfo() {
      for (var i = 0; i < this.gamepads.length; i++) {
        var gamepad = this.gamepads[i];
        if (gamepad.id.includes("Joystick")) {
          this.situationIndex = i;
          console.log("读取到方向控制器，此时i为：", i, this.situationIndex);
          this.startSituationGamepad();
          console.log("控制器类型: 方向控制器");
        } else if (gamepad.id.includes("Throttle")) {
          this.speedIndex = i;
          console.log("读取到速度控制器，此时i为：", i, this.speedIndex);
          this.startSpeedGamepad();
          console.log("控制器类型: 速度控制器");
        } else if (gamepad.id.includes("T-Pendular")) {
          this.balanceIndex = i;
          console.log("读取到平衡控制器，此时i为：", i, this.balanceIndex);
          this.startSituationBalanceGamepad();
          console.log("控制器类型: 平衡控制器");
        } else {
          console.log("控制器类型: 未知");
        }
      }
    },
    //平衡控制器开始方法
    startSituationBalanceGamepad() {
      console.log("开始轮询平衡控制器的输入");
      this.requestAnimationBalanceFrameId = requestAnimationFrame(
        this.balanceGamepad
      );
    },
    //平衡控制器停止方法
    stopSituationBalanceGamepad() {
      console.log("停止轮询平衡控制器的输入");
      cancelAnimationFrame(this.requestAnimationBalanceFrameId);
    },
    //方向控制器开始方法
    startSituationGamepad() {
      console.log("开始轮询方向控制器的输入");
      this.requestAnimationFrameId = requestAnimationFrame(this.pollGamepad);
    },
    //方向控制器停止方法
    stopSituationGamepad() {
      console.log("停止轮询方向控制器的输入");
      cancelAnimationFrame(this.requestAnimationFrameId);
    },
    //速度控制器开始方法
    startSpeedGamepad() {
      console.log("开始轮询速度控制器的输入");
      this.requestAnimationSpeedFrameId = requestAnimationFrame(
        this.speedGamepad
      );
    },
    //速度控制器停止方法
    stopSpeedGamepad() {
      console.log("停止轮询速度控制器的输入");
      cancelAnimationFrame(this.requestAnimationSpeedFrameId);
    },
    //平衡控制器方法
    balanceGamepad() {
      var gamepads = navigator.getGamepads().filter((item) => item != null);
      if (!gamepads || !gamepads[this.balanceIndex]) {
        console.log("平衡控制器未连接或无效，停止轮询", gamepads);
        this.stopSituationBalanceGamepad();
        return;
      }
      var gamepad = gamepads[this.balanceIndex];
      let axis = gamepad.axes[2].toFixed(2);
      this.$store.commit("updateModelParmas", { pedalX: axis.toString() });
      this.$store.commit("setTroubdSpeed", axis);
      this.requestAnimationBalanceFrameId = requestAnimationFrame(
        this.balanceGamepad
      );
    },
    //方向控制器方法
    pollGamepad() {
      const that = this;
      var gamepads = navigator.getGamepads().filter((item) => item != null);
      if (!gamepads || !gamepads[this.situationIndex]) {
        console.log("方向控制器未连接或无效，停止轮询", gamepads);
        this.stopSituationGamepad();
        return;
      }
      var gamepad = gamepads[this.situationIndex];
      var axisX = gamepad.axes[0];
      var axisY = gamepad.axes[1];
      this.$store.commit("updateModelParmas", {
        directionX: axisX.toFixed(1).toString(),
        directionY: axisX.toFixed(1).toString(),
      });
      this.moveBall(axisX, axisY);
      for (var j = 0; j < gamepad.buttons.length; j++) {
        var button = gamepad.buttons[j];
        if (button.pressed) {
          if (j === 1 && !this.isFiring) {
            this.isFiring = true;
            setTimeout(() => {
              this.getDomXY();
              this.isFiring = false;
            }, 300);
          }
          console.log("游戏方向控制器上的按钮 " + j + " 被按下");
        }
      }
      this.requestAnimationFrameId = requestAnimationFrame(this.pollGamepad);
    },
    //速度控制器方法
    speedGamepad() {
      var gamepads = navigator.getGamepads().filter((item) => item != null);
      if (!gamepads || !gamepads[this.speedIndex]) {
        console.log("速度控制器未连接或无效，停止轮询", gamepads);
        this.stopSpeedGamepad();
        return;
      }
      var gamepad = gamepads[this.speedIndex];
      var axisX = gamepad.axes[2];
      var axisY = gamepad.axes[5];
      this.$store.commit("updateModelParmas", {
        yaoganX: axisX.toFixed(2).toString(),
      });
      axisY = ((-axisY + 1) * 5).toFixed(2);
      axisX = ((-axisX + 1) * 5).toFixed(2);
      this.$store.commit("setBgSpeed", axisX);
      // console.log("axisX:", axisX);
      for (var j = 0; j < gamepad.buttons.length; j++) {
        var button = gamepad.buttons[j];
        if (button.pressed) {
          console.log("游戏速度控制器上的按钮 " + j + " 被按下");
        }
      }
      this.requestAnimationSpeedFrameId = requestAnimationFrame(
        this.speedGamepad
      );
    },
    //控制模型移动
    moveBall(axisX, axisY) {
      let rotateZ = axisX.toFixed(1) * 90;
      let rotateX = axisY.toFixed(1) * 30;
      document.documentElement.style.setProperty(
        "--rotateZ-plane",
        `${rotateZ}deg`
      );
      document.documentElement.style.setProperty(
        "--rotateX-plane",
        `${-rotateX}deg`
      );
      var newX = this.plane.offsetLeft + axisX * this.rockerSpeed;
      var newY = this.plane.offsetTop + axisY * this.rockerSpeed;
      newX = Math.max(
        0,
        Math.min(this.gameContiner.offsetWidth - this.plane.offsetWidth, newX)
      );
      newY = Math.max(
        0,
        Math.min(this.gameContiner.offsetHeight - this.plane.offsetHeight, newY)
      );
      this.plane.style.left = newX + "px";
      this.plane.style.top = newY + "px";
      const planeOffset = {
        planeOffsetX: newX.toFixed(2),
        planeOffsetY: newY.toFixed(2),
      };
      this.$store.commit("updateFlyDataKey", planeOffset);
    },
  },
  //监听

  mounted() {
    this.initPlan(); // 初始化飞机
    this.getDomHeight();
    this.initCanvas(); // 初始化 Canvas
    this.destoryFun = pubsub.subscribe("planeGame", () => {
      // this.destroy();
      setTimeout(() => {
        pubsub.publish("refshow1");
      }, 200);
    });
    pubsub.subscribe("refshow2", () => {
      window.location.reload();
    });
  },
  watch: {
    //敌机数组监听
    dijiArr: {
      deep: true, //深度监听
      handler: function (newval) {
        if (!this.plane) {
          console.log("暂时没有敌机");
          return;
        }
        try {
          //清空画布
          this.takeViewCtx.clearRect(
            0,
            0,
            this.takeView.width,
            this.takeView.height
          );
        } catch (error) {}
        //绘制总览敌机圆点
        newval.forEach((enemy, enemyIndex) => {
          let enemyLeft = enemy.x;
          let enemyRight = enemy.x + 120; // 爱心的宽度
          let enemyBottom = enemy.y + 50; // 爱心的高度
          let planeLeft = this.plane.offsetLeft;
          let planeRight = planeLeft + this.plane.width;
          let planeTop = this.plane.offsetTop;
          this.drawPlane(enemy.x, enemy.y, "red");
          if (
            enemyRight > planeLeft &&
            enemyLeft < planeRight &&
            enemyBottom > planeTop &&
            enemyBottom - planeTop < 140
          ) {
            this.dijiArr.splice(enemyIndex, 1);
            let dijiEnvet = {
              time: new Date().getTime(),
              code: "dijiEnvet",
            };

            this.getWebSocket.send(JSON.stringify(dijiEnvet));
            let explosion = { x: enemy.x, y: enemy.y };
            this.explosions.push(explosion);
            setTimeout(() => {
              this.explosions.splice(this.explosions.indexOf(explosion), 1);
            }, 500);
            this.planeSocer.crash++;
            // let crashEnvet = {
            //   time: new Date().getTime(),
            //   code: "crashEnvet",
            // };
            // this.getWebSocket.send(JSON.stringify(crashEnvet));
          }
        });
        this.awardArr.forEach((award) => {
          this.drawAward(award.x, award.y, "gold"); // 绘制金色的圆点来表示爱心奖励
        });
        this.drawPlane(
          this.plane.offsetLeft,
          this.plane.offsetTop + this.boxHeight / 3,
          "white"
        );
      },
      immediate: true,
    },
    //子弹数组监听
    zidanArr: {
      deep: true, //深度监听
      handler: function (newval) {
        newval.forEach((bullet, bulletIndex) => {
          this.dijiArr.forEach((enemy, enemyIndex) => {
            let bulletLeft = bullet.x;
            let bulletRight = bullet.x + 30;
            let bulletTop = bullet.y;
            let bulletBottom = bullet.y + 64;
            let enemyLeft = enemy.x;
            let enemyRight = enemy.x + 120;
            let enemyTop = enemy.y;
            let enemyBottom = enemy.y + 100;
            if (
              bulletRight > enemyLeft &&
              bulletLeft < enemyRight &&
              bulletBottom > enemyTop &&
              bulletTop < enemyBottom
            ) {
              let explosion = { x: enemy.x, y: enemy.y };
              this.explosions.push(explosion);
              setTimeout(() => {
                this.explosions.splice(this.explosions.indexOf(explosion), 1);
              }, 500);
              this.zidanArr.splice(bulletIndex, 1);
              this.dijiArr.splice(enemyIndex, 1);
              let zidanEnvet = {
                time: new Date().getTime(),
                code: "zidanEnvet",
              };

              this.getWebSocket.send(JSON.stringify(zidanEnvet));
              this.planeSocer.strike++;
            }
          });
        });
      },
      immediate: true,
    },
    awardArr: {
      deep: true,
      handler: function (newval) {
        if (!this.plane) {
          console.log("暂时没有敌机");
          return;
        }
        try {
          //清空画布
          this.takeViewCtx.clearRect(
            0,
            0,
            this.takeView.width,
            this.takeView.height
          );
        } catch (error) {}
        newval.forEach((award, awardIndex) => {
          let awardLeft = award.x;
          let awardRight = award.x + 50; // 爱心的宽度
          let awardBottom = award.y + 50; // 爱心的高度
          let planeLeft = this.plane.offsetLeft;
          let planeRight = planeLeft + this.plane.width;
          let planeTop = this.plane.offsetTop;
          this.drawAward(award.x, award.y, "gold"); // 绘制金色的圆点来表示爱心奖励
          if (
            awardRight > planeLeft &&
            awardLeft < planeRight &&
            awardBottom > planeTop &&
            awardBottom - planeTop < 140
          ) {
            this.planeSocer.score++;
            let heartsion = { x: award.x, y: award.y };
            this.heartsions.push(heartsion);
            this.awardArr.splice(awardIndex, 1);
            let heartEnvet = {
              time: new Date().getTime(),
              code: "heartEnvet",
            };

            this.getWebSocket.send(JSON.stringify(heartEnvet));
            setTimeout(() => {
              this.heartsions.splice(this.heartsions.indexOf(heartsion), 1);
            }, 500);
          }
        });
        this.dijiArr.forEach((enemy) => {
          this.drawPlane(enemy.x, enemy.y, "red");
        });
        this.drawPlane(
          this.plane.offsetLeft,
          this.plane.offsetTop + this.boxHeight / 3,
          "white"
        );
      },
      immediate: true,
    },
  },
  created() {},
};
</script>

<style lang="scss" scoped>
* {
  margin: 0;
  padding: 0;
}
.takeView {
  position: absolute;
  top: 0;
  right: 0;
  width: 280px;
  height: 180px;
  margin: 10px;
  z-index: 3;
  overflow: hidden;
  background: #000000;
  box-shadow: 0px 0px 8px 0px rgba(4, 22, 29, 0.4),
    0px 0px 16px 0px rgba(174, 182, 185, 0.4);
  border-radius: 12px;
  opacity: 0.7;
  canvas {
    width: 120%;
    height: 100%;
    border-radius: 0%;
  }
}
.app {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  position: absolute;
  .box {
    width: 100%;
    height: 100vh;
    position: relative;
    .plane {
      width: 120px; /* 调整大小 */
      height: 140px; /* 调整大小 */
      position: absolute;
      z-index: 2;
      left: 50%;
      bottom: 20%;
      transform: translateX(-50%) rotateZ(var(--rotateZ-plane))
        rotateX(var(--rotateX-plane));
      transition: transform 0.1s ease-in-out;
    }
    .zidan {
      width: 30px;
      height: 64px;
      background-image: url("../../../../assets/images/zidan.png");
      background-size: contain;
      background-position: center;
      background-repeat: no-repeat;
      position: absolute;
      z-index: 1;
    }
    .diji {
      width: 120px; /* 调整大小 */
      height: 100px; /* 调整大小 */
      position: absolute;
    }
    .explosion {
      width: 120px; /* 根据爆炸效果调整大小 */
      height: 120px; /* 根据爆炸效果调整大小 */
      position: absolute;
      z-index: 10; /* 使爆炸效果位于顶层 */
    }
    .award {
      width: 50px; /* 调整大小 */
      height: 50px; /* 调整大小 */
      position: absolute;
    }
  }
  .model {
    width: 70vw;
    position: fixed;
    left: 25%;
    bottom: 13%;
    display: flex;
    flex-flow: row;
    justify-content: space-between;
    .model-item {
      width: 40%;
      display: flex;
      flex-flow: row;
      justify-content: center;
      align-items: center;
    }
  }
}
</style>
